EN = 0b10000000
RW = 0b01000000
RS = 0b00100000

start:
  ldr OPB, #0b00111000       ; set 8-bit mode, 2-line display, 5x8 font
  call lcd_instruction
  
  ldr OPB, #0b00001100       ; set display on, curson off, blink off 
  call lcd_instruction

  ldr OPB, #0b00000110       ; increment and shift cursor
  call lcd_instruction

  ldr OPB, #0b00000001       ; clear display, put cursor in first pos in first line
  call lcd_instruction

init_score_values:
  ldr D, #0xFD           ; end_score - 2
  ldr C, #0x04
  ldr A, #0x30

init_score_values_loop:
  stm A, $D
  dec D
  dec C
  jmnz init_score_values_loop

init_score_line:
  ldr D, top_line_text       ; address of top line is in D

init_score_line_loop:
  ldm $D, A                  ; char pointed to by D is now in A
  cmp #0x00                  ; compare with zero

  jmz init_player_pos

  mov A, OPB                ; letter is in reg. A
  call lcd_character
  
  inc D

  jump init_score_line_loop
  
init_player_pos:
  ldr B, #0x80              ; 0x00 = ground, 0x80 = air, last 5 bits = counter

init_obstacles:
  ldr C, #0x01

main_loop:

  call update_score

  call get_input

  ror C

  call update_obstacles_left
  call update_obstacles_right

  ; check if player collides with obstacle
  mov C, A
  and #0b00000100
  cllnz check_collision

  ; check if player is in the air, increment counter if yes
  mov B, A
  and #0x80
  jmz skip_incrementing_counter_player_airtime_end

  mov B, A
  and #0x0f
  cmp #3
  jmz skip_incrementing_counter_player_airtime_end
  inc B
  jump main_loop

skip_incrementing_counter_player_airtime_end:
  ldr B, #0x00
  call print_player_ground 
  jump main_loop

check_collision:
  mov B, A
  and #0x80
  
  jmz game_over

  cllnz increment_score_in_memory
  ret
  
game_over:
  ldr OPB, #0x80               ; cursor at first pos
  call lcd_instruction
  ldr OPB, #0x3A               ; ":"
  call lcd_character
  ldr OPB, #0x28               ; "("
  call lcd_character
  hlt

get_input:
  mov IPA, A
  and #0x80
  rtnz              ; nothing pressed - return        not zero => msb one => not pressed since msb is active low

  mov B, A
  and #0x80
  rtnz              ; player in air - return

  ldr B, #0x80     ; set player in air, counter to zero
  call print_player_air

  ret

print_player_ground:
  ldr OPB, #0x82
  call lcd_instruction
  ldr OPB, #0x20
  call lcd_character

  ldr OPB, #0xC2
  call lcd_instruction
  ldr OPB, #0xFB
  call lcd_character

  ret

print_player_air:
  ldr OPB, #0xC2
  call lcd_instruction
  ldr OPB, #0x20
  call lcd_character

  ldr OPB, #0x82
  call lcd_instruction
  ldr OPB, #0xFB
  call lcd_character

  ret

update_obstacles_left:
  ldr OPB, #0xC0
  call lcd_instruction
  jump update_obstacles_init

update_obstacles_right:
  ldr OPB, #0xC8
  call lcd_instruction
  jump update_obstacles_init

update_obstacles_init:
  mov C, D
  ldr C, #0x01

update_obstacles_loop:
  mov D, A
  and C
  jmnz print_obstacle

print_space:
  ldr OPB, #0x20
  call lcd_character
  jump shift_obstacle_register

print_obstacle:
  ldr OPB, #0xFF
  call lcd_character

shift_obstacle_register:
  shl C
  
  jmz return_from_obstacle_print

  jump update_obstacles_loop

return_from_obstacle_print:
  mov D, C
  ret

update_score:

  ldr OPB, #0x8C                ; move cursor to first line, Cth (12th) position
  call lcd_instruction

  ldr D, score_text            ; address of lcd_text is now in D

update_score_loop:
  ldm $D, A                  ; char pointed to by D is now in A
  cmp #0x00                  ; compare with zero

  jmz update_score_end

  mov A, OPB                ; letter is in reg. A
  call lcd_character
  
  inc D

  jump update_score_loop

update_score_end:
  ;ldr OPB, #0b11000000        ; put cursor at the start of second line
  ;call lcd_instruction
  ret

increment_score_in_memory:
  ldr D, #0xFD           ; address right after the last digit of score is in D          !!!!! end_score-2

  ldm $D, A                  ; value of ones place is in A
  cmp #0x39                  ; compare with 0x39 - "9"

  jmz digit_overflow         ; ones overflow to tens

increment_current_digit:
  inc A                      
  stm A, $D                  ; otherwise increment A and store the same character to memory
  ret                        ; then return

digit_overflow:
  ldr A, #0x30               ; load "0" to A
  stm A, $D                  ; zero is now in ones place in memory

  dec D                      ; D now pointing to higher value

  ldm $D, A                  ; value of higher place is in A
  cmp #0x39                  ; compare to 9

  jmz digit_overflow

  cmp #0x20                  ; compare to " " - end loop

  jump increment_current_digit

lcd_instruction:
  ldr OPA, #0               ; clear RS/RW/EN bits
  ldr OPA, EN               ; toggle ENable pin
  ldr OPA, #0               ; clear RS/RW/EN bits
  ret

lcd_character:
  ldr OPA, RS               ; set RS bit
  ldr OPA, #0b10100000      ; toggle ENable pin
  ldr OPA, RS               ; clear ENable bit
  ret


;            0123456789abcdef
;           "     Score: 0000"

top_line_text: ascii "     Score: "
score_text: asciiz "0000"        ; 0 - 0x30; 9 - 0x39
end_score: